package com.example.tool.advisor;

import com.example.tool.R.R;
import com.example.tool.anno.ExceptionType;
import com.example.tool.exception.ServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * 全局异常处理器
 * @author zhanglong
 * @date 2023/10/24
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    @Autowired
    private MessageSource messageSource;

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R handleMethodArgumentNotValidException(MethodArgumentNotValidException e){
        BindingResult result = e.getBindingResult();
        // 包名.类名.属性名.注解名
        List<FieldError> fieldErrors = result.getFieldErrors();
        StringBuilder msg = new StringBuilder();
        for (FieldError error : fieldErrors) {
            String messageKey = String.join(
                    ".",
                    Objects.requireNonNull(result.getTarget()).getClass().getName() ,
                    error.getField() ,
                    error.getCode()
            );
            msg.append(
                            messageSource.getMessage(
                                    messageKey,null,error.getDefaultMessage(), LocaleContextHolder.getLocale()
                            )
                    )
                    .append(";");
        }
        return R.fail(msg.toString());
    }


    @ExceptionHandler(ServiceException.class)
    public R handleException(ServiceException e){
        return Optional.ofNullable(e.getClass().getDeclaredAnnotation(ExceptionType.class))
                .orElse(ServiceException.class.getDeclaredAnnotation(ExceptionType.class))
                .value()
                .result();
    }


}
